package com.yueke.commom.ribbon.rules;

import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.ribbon.NacosServer;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.client.naming.core.Balancer;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.Server;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @program: yueke-parent
 * @description: WeightRule,自定义权重负载均衡规则，优先匹配当前服务同集群下的其他节点
 * @author: XiYang
 * @create: 2020-10-13 19:15
 **/
public class ClusterWeightRule extends AbstractLoadBalancerRule {
    @Autowired
    private NacosDiscoveryProperties nacosDiscoveryProperties;

    @Override
    public Server choose(Object o) {
        try {
            //获取当前服务所在的集群名
            String clusterName = nacosDiscoveryProperties.getClusterName();
            //拿到要访问的服务名称
            BaseLoadBalancer loadBalancer = (BaseLoadBalancer)this.getLoadBalancer();
            String serviceName = loadBalancer.getName();
            //通过服务名在nacos上面获取相同集群下的实例
            NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
            //获取"要访问的服务"所在的集群的集合
            List<Instance> instances = namingService.selectInstances(serviceName, true);
            //过滤当前服务所在的集群，并以流的方式放进新集合
            List<Instance> instanceList = instances.stream().filter(instance -> {
                return StringUtils.equals(instance.getClusterName(), clusterName);
            }).collect(Collectors.toList());
            //如果当前集群无符合节点，则还使用过滤前的集群集合
            if (CollectionUtils.isEmpty(instanceList)) {
                instanceList= instances;
            }
            //通过权重算法从集合中获取一个instance
            Instance weightInstance = Mybalancer.getWeightInstance(instanceList);
            //返回
            return new NacosServer(weightInstance);
        } catch (NacosException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {

    }

    static class Mybalancer extends Balancer {
        public static Instance getWeightInstance(List<Instance> hosts){
            return getHostByRandomWeight(hosts);
        }
    }
}
